home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / ODF Release 3 / ODFDev / Form / Sources / EditCmd.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  16.1 KB  |  514 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                EditCmd.cpp
  4. //    Release Version:    $ ODF 3 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "Form.hpp"
  11.  
  12. #ifndef EDITCMD_H
  13. #include "EditCmd.h"
  14. #endif
  15.  
  16. #ifndef FWEDVIEW_H
  17. #include "FWEdView.h"
  18. #endif
  19.  
  20. #ifndef FWFRAME_H
  21. #include "FWFrame.h"
  22. #endif
  23.  
  24. #ifndef FWPART_H
  25. #include "FWPart.h"
  26. #endif
  27.  
  28. #ifndef FWUTIL_H
  29. #include "FWUtil.h"
  30. #endif
  31.  
  32. #ifndef FWKIND_H
  33. #include "FWKind.h"
  34. #endif
  35.  
  36. // for FW_CPartKindIterator
  37. #ifndef FWPRTITE_H
  38. #include "FWPrtIte.h"
  39. #endif
  40.  
  41. #ifndef FWSUSINK_H
  42. #include "FWSUSink.h"
  43. #endif
  44.  
  45. #ifndef FWBARRAY_H
  46. #include "FWBArray.h"
  47. #endif
  48.  
  49. #ifndef FWSUUTIL_H
  50. #include "FWSUUtil.h"
  51. #endif
  52.  
  53. #ifndef SOM_Module_OpenDoc_Commands_defined
  54. #include "CmdDefs.xh"
  55. #endif
  56.  
  57. //========================================================================================
  58. // RunTime Info
  59. //========================================================================================
  60.  
  61. #ifdef FW_BUILD_MAC
  62. #pragma segment odfform
  63. #endif
  64.  
  65. FW_DEFINE_AUTO(CEditViewCommand)
  66.  
  67. //========================================================================================
  68. //    class FW_CEditViewCommand
  69. //========================================================================================
  70.  
  71. //----------------------------------------------------------------------------------------
  72. //    CEditViewCommand constructor
  73. //----------------------------------------------------------------------------------------
  74. CEditViewCommand::CEditViewCommand(Environment* ev, 
  75.                             ODCommandID commandID,
  76.                             FW_CFrame* frame,
  77.                             FW_Boolean canUndo)
  78. :    FW_CClipboardCommand(ev, commandID, frame, canUndo),
  79.     FW_MReceiver(),
  80.     fOwnsSelection(false),
  81.     fEditView(0),
  82.     fStartOffset(0),
  83.     fEndOffset(0)
  84. {
  85. }
  86.  
  87. //----------------------------------------------------------------------------------------
  88. //    CEditViewCommand destructor
  89. //----------------------------------------------------------------------------------------
  90.  
  91. CEditViewCommand::~CEditViewCommand()
  92. {
  93.     if (fOwnsSelection)
  94.         delete fSelection;        // Selection was created on the fly in DoMenu
  95. }
  96.  
  97. //----------------------------------------------------------------------------------------
  98. //    CEditViewCommand::SetEditView
  99. //----------------------------------------------------------------------------------------
  100. // SetEditView must be called right after the creation of the CEditViewCommand in order
  101. // to initialize the fEditView attribut because FW_CFrame::NewClipboardCommand doesn't let
  102. // us pass arguments.  See CScrollEdit::DoMenu().
  103.  
  104. void CEditViewCommand::SetEditView(FW_CEditView* editView)
  105. {
  106.     fEditView = editView;
  107.     
  108.     // [LSD] work-around to notify & disable the command when the edit view is deleted
  109.     // See CEditViewCommand::HandleNotification
  110.     AddInterest(FW_CInterest(editView, FW_kNotifierDeletedMsg));
  111. }
  112.  
  113. //----------------------------------------------------------------------------------------
  114. //    CEditViewCommand::HandleNotification
  115. //----------------------------------------------------------------------------------------
  116. // 
  117. void CEditViewCommand::HandleNotification(Environment* ev, const FW_CNotification& notification) 
  118. {
  119. FW_UNUSED(ev);
  120.     if (notification.GetMessage() == FW_kNotifierDeletedMsg)
  121.     {
  122.         // [LSD] The edit view associated with this command has been deleted.  We cannot
  123.         // delete the command ourselves, it belongs to OpenDoc Undo stack, but we must
  124.         // disable it to avoid any trouble in RedoIt & UndoIt.
  125.         fEditView = 0;
  126.     }
  127. }
  128.  
  129. //----------------------------------------------------------------------------------------
  130. //    CEditViewCommand::PreCommand
  131. //----------------------------------------------------------------------------------------
  132.  
  133. void CEditViewCommand::PreCommand(Environment* ev)
  134. {
  135.     ODCommandID id = GetCommandID(ev);
  136.     
  137.     if ((id == kODCommandCopy) || (id == kODCommandCut))
  138.         fEditView->DoTECommand(ev, kODCommandCopy, true);    // Tell TE to copy the text
  139. }
  140.  
  141. //----------------------------------------------------------------------------------------
  142. //    CEditViewCommand::CommandDone
  143. //----------------------------------------------------------------------------------------
  144. /*
  145. void CEditViewCommand::CommandDone(Environment* ev)
  146. {
  147.     // If fEditView belongs to your part's content you may want to notify it of the change
  148.     switch (GetCommandID(ev))
  149.     {
  150.         case kODCommandCut:
  151.         case kODCommandPaste:
  152.         case kODCommandClear:
  153.             fEditView->Notify(ev, CEditNotification(fEditView));
  154.     }
  155. }
  156. */
  157.  
  158. //----------------------------------------------------------------------------------------
  159. //    CEditViewCommand::SaveUndoState
  160. //----------------------------------------------------------------------------------------
  161. void CEditViewCommand::SaveUndoState(Environment* ev)
  162. {
  163.     switch (GetCommandID(ev))
  164.     {
  165.         case kODCommandCut:
  166.         case kODCommandClear:
  167.             fPastedText = fEditView->GetSelectedText(ev);
  168.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  169.             break;
  170.  
  171.         case kODCommandPaste:
  172.             fSavedText = fEditView->GetSelectedText(ev);
  173.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  174.             break;
  175.     }
  176. }
  177.  
  178. //----------------------------------------------------------------------------------------
  179. //    CEditViewCommand::SaveRedoState
  180. //----------------------------------------------------------------------------------------
  181. void CEditViewCommand::SaveRedoState(Environment* ev)
  182. {
  183.     if (GetCommandID(ev) == kODCommandPaste)
  184.     {
  185.         CEditViewSelContent* selContent = (CEditViewSelContent*)fSelection->GetSelectedContent(ev);
  186.         fPastedText = selContent->GetInternalizedText(ev);
  187.     }
  188. }
  189.  
  190. //----------------------------------------------------------------------------------------
  191. //    CEditViewCommand::UndoIt
  192. //----------------------------------------------------------------------------------------
  193.  
  194. void CEditViewCommand::UndoIt(Environment* ev)
  195. {
  196.     FW_CClipboardCommand::UndoIt(ev);    // call inherited
  197.  
  198.     // Don't do anything if command is disabled
  199.     if (fEditView == NULL)
  200.         return;
  201.         
  202.     switch (GetCommandID(ev))
  203.     {
  204.         case kODCommandCut:
  205.         case kODCommandClear:
  206.             this->RestoreText(ev);
  207.             break;
  208.  
  209.         case kODCommandPaste:
  210.             this->RemoveAndRestoreText(ev, fPastedText.GetByteLength(), fSavedText);
  211.             break;
  212.     }    
  213. }
  214.  
  215. //----------------------------------------------------------------------------------------
  216. //    CEditViewCommand::RedoIt
  217. //----------------------------------------------------------------------------------------
  218. void CEditViewCommand::RedoIt(Environment* ev)
  219. {
  220.     FW_CClipboardCommand::RedoIt(ev);    // call inherited
  221.  
  222.     // Don't do anything if command is disabled
  223.     if (fEditView == NULL)
  224.         return;
  225.  
  226.     switch (GetCommandID(ev))
  227.     {
  228.         case kODCommandCut:
  229.         case kODCommandClear:
  230.             this->RemoveText(ev);
  231.             break;
  232.  
  233.         case kODCommandPaste:
  234.             this->RemoveAndRestoreText(ev, fSavedText.GetByteLength(), fPastedText);
  235.             break;
  236.     }    
  237. }
  238.  
  239. //----------------------------------------------------------------------------------------
  240. //    CEditViewCommand::RemoveText
  241. //----------------------------------------------------------------------------------------
  242.  
  243. void CEditViewCommand::RemoveText(Environment* ev)
  244. {
  245.     FW_ASSERT(fEditView);
  246.  
  247.     fEditView->SelectText(ev, fStartOffset, fEndOffset);
  248.     fEditView->DoTECommand(ev, kODCommandClear, false);
  249.  
  250.     // If fEditView belongs to your part's content you may want to notify it of the change
  251. //    fEditView->Notify(ev, CEditNotification(fEditView));
  252. }
  253.  
  254. //----------------------------------------------------------------------------------------
  255. //    CEditViewCommand::RestoreText
  256. //----------------------------------------------------------------------------------------
  257.  
  258. void CEditViewCommand::RestoreText(Environment* ev)
  259. {
  260.     FW_ASSERT(fEditView);
  261.  
  262.     // Insert the saved text back into the EditView
  263.     fEditView->InsertText(ev, fPastedText, fStartOffset);
  264.  
  265.     // If fEditView belongs to your part's content you may want to notify it of the change
  266. //    fEditView->Notify(ev, CEditNotification(fEditView));   
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270. //    CEditViewCommand::RemoveAndRestoreText
  271. //----------------------------------------------------------------------------------------
  272.  
  273. void CEditViewCommand::RemoveAndRestoreText(Environment* ev, FW_ByteCount bytesToRemove,
  274.                                                 const FW_CString& textToRestore)
  275. {
  276.     FW_ASSERT(fEditView);
  277.  
  278.     // Remove designated text
  279.     fEditView->SelectText(ev, fStartOffset, fStartOffset+(short)bytesToRemove);
  280.     fEditView->DoTECommand(ev, kODCommandClear, false);
  281.  
  282.     // Restore the text
  283.     fEditView->InsertText(ev, textToRestore, fStartOffset);
  284.  
  285.     // If fEditView belongs to your part's content you may want to notify it of the change
  286. //    fEditView->Notify(ev, CEditNotification(fEditView));
  287. }
  288.  
  289. #pragma mark -
  290. //========================================================================================
  291. //    CLASS CEditViewSelection
  292. //========================================================================================
  293.  
  294. FW_DEFINE_AUTO(CEditViewSelection)
  295.  
  296. //---------------------------------------------------------------------------------------
  297. //    CEditViewSelection constructor
  298. //---------------------------------------------------------------------------------------
  299.  
  300. CEditViewSelection::CEditViewSelection(Environment* ev, FW_CEditView* editview) :
  301.     FW_CSelection(ev, false, false),
  302.     fSelectedContent(NULL)
  303. {
  304.     fSelectedContent = FW_NEW(CEditViewSelContent, (ev, editview));
  305. }
  306.  
  307. //---------------------------------------------------------------------------------------
  308. //    CEditViewSelection destructor
  309. //---------------------------------------------------------------------------------------
  310.  
  311. CEditViewSelection::~CEditViewSelection()
  312. {
  313.     delete fSelectedContent;
  314. }
  315.  
  316. //---------------------------------------------------------------------------------------
  317. //    CEditViewSelection::ClearSelection
  318. //---------------------------------------------------------------------------------------
  319.  
  320. void CEditViewSelection::ClearSelection(Environment* ev)
  321. {
  322.     fSelectedContent->ClearSelectedText(ev); 
  323. }
  324.  
  325. //---------------------------------------------------------------------------------------
  326. //    CEditViewSelection::CloseSelection
  327. //---------------------------------------------------------------------------------------
  328.  
  329. void CEditViewSelection::CloseSelection(Environment* ev)
  330. {
  331.     fSelectedContent->UnselectText(ev);
  332. }
  333.  
  334. //---------------------------------------------------------------------------------------
  335. //    CEditViewSelection::IsEmpty
  336. //---------------------------------------------------------------------------------------
  337.  
  338. FW_Boolean CEditViewSelection::IsEmpty(Environment* ev) const
  339. {
  340.     return fSelectedContent->IsEmpty(ev);
  341. }
  342.  
  343. //---------------------------------------------------------------------------------------
  344. //    CEditViewSelection::SelectAll
  345. //---------------------------------------------------------------------------------------
  346.  
  347. void CEditViewSelection::SelectAll(Environment* ev)
  348. {
  349. FW_UNUSED(ev);
  350.     // This function is handled by the current EditView
  351. }
  352.  
  353. #pragma mark -
  354. //========================================================================================
  355. //    CEditViewSelContent class
  356. //========================================================================================
  357.  
  358. FW_DEFINE_AUTO(CEditViewSelContent)
  359.  
  360. //----------------------------------------------------------------------------------------
  361. // CEditViewSelContent constructor
  362. //----------------------------------------------------------------------------------------
  363. CEditViewSelContent::CEditViewSelContent(Environment* ev, FW_CEditView* editview) :
  364.     FW_CContent(ev, editview->GetFrame(ev)->GetPart(ev)),
  365.     fEditView(editview)
  366. {
  367. }
  368.  
  369. //----------------------------------------------------------------------------------------
  370. // CEditViewSelContent destructor
  371. //----------------------------------------------------------------------------------------
  372.  
  373. CEditViewSelContent::~CEditViewSelContent()
  374. {
  375. }
  376.  
  377. //----------------------------------------------------------------------------------------
  378. // CEditViewSelContent::ExternalizeKind
  379. //----------------------------------------------------------------------------------------
  380. void CEditViewSelContent::ExternalizeKind(Environment* ev,
  381.                                     ODStorageUnit* storageUnit,
  382.                                     FW_CKind* kind,
  383.                                     FW_StorageKinds storageKind,
  384.                                     FW_CPromise* promise,
  385.                                     FW_CCloneInfo* cloneInfo)
  386. {
  387. FW_UNUSED(cloneInfo);
  388. FW_UNUSED(storageKind);
  389. FW_UNUSED(promise);
  390.  
  391.     if (kind->IsEqual(ev, 'TEXT', kODPlatformDataType))
  392.     {
  393.         // Write the selected string in Mac 'TEXT' format
  394.         FW_CString selectedText = fEditView->GetSelectedText(ev);
  395.         FW_PStorageUnitSink suSink(ev, storageUnit, kODPropContents, kind->GetType(ev));
  396.         FW_CWritableStream stream(suSink);
  397.         stream.Write(selectedText.RevealBuffer(), selectedText.GetByteLength());
  398.     }
  399. }
  400.  
  401. //----------------------------------------------------------------------------------------
  402. // CEditViewSelContent::Internalizekind
  403. //----------------------------------------------------------------------------------------
  404.  
  405. FW_Boolean CEditViewSelContent::InternalizeKind(Environment* ev,
  406.                                          ODStorageUnit* sourceSU, 
  407.                                          FW_CKind* kind,
  408.                                          FW_StorageKinds storageKind,
  409.                                          FW_CCloneInfo* cloneInfo)
  410. {
  411. FW_UNUSED(cloneInfo);
  412. FW_UNUSED(storageKind);
  413.     FW_ASSERT(fEditView);
  414.     
  415.     // Compute the maximum number of characters that can be added to the edit view
  416.     short startSel, endSel;
  417.     fEditView->GetSelectionRange(ev, startSel, endSel);
  418.     FW_ByteCount notSelectedChars = fEditView->GetTextLength(ev) - (endSel - startSel);
  419.     if (notSelectedChars >= fEditView->GetMaxChars(ev))
  420.         return false;
  421.  
  422.     FW_Boolean internalized = false;
  423.     FW_ByteCount maxChars = fEditView->GetMaxChars(ev) - notSelectedChars;
  424.     FW_CString selectedText;
  425.  
  426.     // Don't want to internalize the part kind into an editView, so find the next supported kind
  427.     FW_CPartKindIterator it(GetPart(ev));
  428.     for (FW_CKind* kin = it.First(); it.IsNotComplete(); kin = it.Next())
  429.     {
  430.         if (!kin->IsPartKind(ev))
  431.         {
  432.             if (kin->ImportSupported(ev, storageKind))
  433.                 if (sourceSU->Exists(ev, kODPropContents, kin->GetType(ev), 0))
  434.                 {
  435.                     kind = kin;
  436.                     break;
  437.                 }
  438.         }
  439.     }
  440.  
  441.     if (kind->IsEqual(ev, 'TEXT', kODPlatformDataType))
  442.     {
  443.         // Internalize the 'TEXT' type
  444.         if (FW_SUExistsThenFocus(ev, sourceSU, kODPropContents, kind->GetType(ev)))    
  445.             internalized = InternalizeText(ev, sourceSU, selectedText, maxChars);
  446.  
  447.         if (internalized)
  448.         {
  449.             fInternalizedText = selectedText;
  450.             fEditView->SetSelectedText(ev, selectedText);
  451.         }
  452.     }
  453.     
  454.     return internalized;
  455. }
  456.  
  457. //----------------------------------------------------------------------------------------
  458. // CEditViewSelContent::ClearSelectedText
  459. //----------------------------------------------------------------------------------------
  460.  
  461. void CEditViewSelContent::ClearSelectedText(Environment* ev)
  462. {
  463.     fEditView->SetSelectedText(ev, FW_CString());
  464. }
  465.  
  466. //----------------------------------------------------------------------------------------
  467. // CEditViewSelContent::UnselectText
  468. //----------------------------------------------------------------------------------------
  469.  
  470. void CEditViewSelContent::UnselectText(Environment* ev)
  471. {
  472.     short startOffset, endOffset; 
  473.     fEditView->GetSelectionRange(ev, startOffset, endOffset);
  474.     fEditView->SelectText(ev, startOffset, startOffset);
  475. }
  476.  
  477. //---------------------------------------------------------------------------------------
  478. //    CEditViewSelContent::IsEmpty
  479. //---------------------------------------------------------------------------------------
  480.  
  481. FW_Boolean CEditViewSelContent::IsEmpty(Environment* ev) const
  482. {
  483.     short startOffset, endOffset; 
  484.     fEditView->GetSelectionRange(ev, startOffset, endOffset);
  485.     return (startOffset == endOffset);
  486. }
  487.  
  488. //----------------------------------------------------------------------------------------
  489. //    InternalizeText
  490. //----------------------------------------------------------------------------------------
  491. // Global function to read text fro a storage unit
  492.  
  493. FW_Boolean InternalizeText(Environment* ev, 
  494.                             ODStorageUnit* storageUnit, 
  495.                             FW_CString& text, 
  496.                             FW_ByteCount  maxChars)
  497. {
  498.     FW_ByteCount textSize = storageUnit->GetSize(ev);
  499.     if (textSize == 0) 
  500.         return false;
  501.         
  502.     if (textSize > maxChars)
  503.         textSize = maxChars;
  504.         
  505.     FW_CByteArray byteArray;
  506.     storageUnit->GetValue(ev, textSize, byteArray);
  507. //    byteArray.CopyBuffer(&buffer, textSize);
  508.     
  509.     text = FW_CString((char *)byteArray.GetBuffer(), textSize);
  510.     
  511.     return true;
  512. }
  513.  
  514.